﻿// ------------------------------------------------------------------------
//    YATSE - A touch screen remote controller for XBMC (.NET 3.5)
//    Copyright (C) 2010  Tolriq (http://code.google.com/p/yatse/)
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
// ------------------------------------------------------------------------

using System;
using System.Collections;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Xml;
using YATSE.Libs;

namespace YATSE
{
    public class NetworkTools
    {
        private const int PingTimeout = 1000;

        [DllImport("iphlpapi.dll", ExactSpelling = true)]
        private static extern int SendARP(int destIp, int srcIp, byte[] pMacAddr, ref uint phyAddrLen);

        public string GetMacAddress(string ipAddress)
        {
            var macAddress = string.Empty;

            if (!IsHostAccessible(ipAddress)) return null;
            try
            {
                var processStartInfo = new ProcessStartInfo
                                           {
                                               FileName = "nbtstat",
                                               RedirectStandardInput = false,
                                               RedirectStandardOutput = true,
                                               Arguments = "-a " + ipAddress,
                                               UseShellExecute = false
                                           };
                var process = Process.Start(processStartInfo);
                var counter = -1;
                while (counter <= -1)
                {
                    counter = macAddress.Trim().ToLower().IndexOf("mac address", 0);
                    if (counter > -1)
                    {
                        break;
                    }
                    if (process != null) macAddress = process.StandardOutput.ReadLine();
                }

                if (process != null) process.WaitForExit();
                macAddress = macAddress.Trim();
            }
            catch (Exception) {}
            return macAddress;
        }

        public static bool IsHostAccessible(string hostNameOrAddress)
        {
            var ping = new Ping();
            var reply = ping.Send(hostNameOrAddress, PingTimeout);
            if (reply != null) return reply.Status == IPStatus.Success;
            return false;
        }

        public static string GetMACAddressFromARP(string hostNameOrAddress)
        {
            if (!IsHostAccessible(hostNameOrAddress)) return null;

            var hostEntry = Dns.GetHostEntry(hostNameOrAddress);
            if (hostEntry.AddressList.Length == 0)
                return null;

            var macAddr = new byte[6];
            var macAddrLen = (uint) macAddr.Length;
            if (SendARP((int) hostEntry.AddressList[0].Address, 0, macAddr, ref macAddrLen) != 0)
                return null;

            var macAddressString = new StringBuilder();
            foreach (var t in macAddr)
            {
                if (macAddressString.Length > 0)
                    macAddressString.Append(":");
                macAddressString.AppendFormat("{0:x2}", t);
            }
            return macAddressString.ToString();
        }

        public static void Wakeup(string macAddress)
        {
            var client = new WolUdpClient();
            client.Connect( new IPAddress(0xffffffff), 0x2fff);
            if (!client.IsClientInBrodcastMode()) return;

            var byteCount = 0;
            var bytes = new byte[102];
            for (var trailer = 0; trailer < 6; trailer++)
            {
                bytes[byteCount++] = 0xFF;
            }
            for (var macPackets = 0; macPackets < 16; macPackets++)
            {
                var i = 0;
                for (var macBytes = 0; macBytes < 6; macBytes++)
                {
                    bytes[byteCount++] = byte.Parse(macAddress.Substring(i, 2), NumberStyles.HexNumber);
                    i += 2;
                }
            }
            client.Send(bytes, byteCount);
        }

        private class WolUdpClient : UdpClient
        {
            public bool IsClientInBrodcastMode()
            {
                var broadcast = false;
                if (Active)
                {
                    try
                    {
                        Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 0);
                        broadcast = true;
                    }
                    catch
                    {
                        broadcast = false;
                    }
                }
                return broadcast;
            }
        }
    }

    public class YatseConfig
    {
        public bool IsConfigured { get; set; }
        public bool Debug { get; set; }
        public bool SecondScreen { get; set; }
        public bool TopMost { get; set; }
        public bool KeepFocus { get; set; }
        public bool ForceResolution { get; set; }
        public bool Diaporama { get; set; }
        public bool Dimming { get; set; }
        public bool Currently { get; set; }
        public bool CurrentlyMovie { get; set; }
        public bool HideCursor { get; set; }
        public bool UseBanner { get; set; }
        public bool ShowOverlay { get; set; }
        public bool ShowEmptyMusicGenre { get; set; }
        public bool ManualRefresh { get; set; }
        public bool ShowScrollBars { get; set; }
        public bool DisableAnimations { get; set; }
        public Devmode Resolution { get; set; }
        public string ImageDirectory { get; set; }
        public string XBMCIp { get; set; }
        public string XBMCPort { get; set; }
        public string XBMCLogin { get; set; }
        public string XBMCPassword { get; set; }
        public string XBMCMac { get; set; }
        public string Language { get; set; }
        public string Skin { get; set; }
    }


    internal class ScreenRes
    {
        public Devmode Mode;

        public ScreenRes(Devmode mode)
        {
            Mode = mode;
        }

        public override string ToString()
        {
            return ScreenResolution.DevmodeToString(Mode);
        }
    }

    public class XmlLang
    {
        private readonly Hashtable _langData = new Hashtable();

        public bool LoadXml(string path)
        {
            if (!File.Exists(path)) return false;
            _langData.Clear();
            var data = new XmlDocument();

            data.Load(path);
            var elements = data.SelectNodes("//strings/string");
            if (elements == null) return false;

            foreach (XmlElement element in elements)
            {
                _langData.Add(element.GetAttribute("id"), element.InnerText);
            }
            return true;
        }

        public string GetString(string id, string fallback)
        {
            if (_langData.ContainsKey(id))
            {
                return (string) _langData[id];
            }
            return fallback;
        }
    }

    public class MusicGenre
    {
        public string Cover { get; set; }
        public string Name { get; set; }
        public string Id { get; set; }
    }

    public class Film
    {
        public string Genre { get; set; }
        public string Title { get; set; }
        public string Tagline { get; set; }
        public string Plot { get; set; }
        public string Director { get; set; }
        public string Year { get; set; }
        public string Duration { get; set; }
        public string IdFile { get; set; }
        public string IdMovie { get; set; }
        public string Rating { get; set; }
        public string FileName { get; set; }
        public string DirName { get; set; }
        public string PlayCount { get; set; }
        public Visibility Seen { get; set; }
        public string Hash { get; set; }
        public string Cover { get; set; }
        public string Fanart { get; set; }
        public string WatchedImage { get; set; }
    }

    public class TvShow
    {
        public string IdShow { get; set; }
        public string Title { get; set; }
        public string Plot { get; set; }
        public string Date { get; set; }
        public string Genre { get; set; }
        public string MPAA { get; set; }
        public string Studio { get; set; }
        public string DirName { get; set; }
        public string TotalCount { get; set; }
        public string Hash { get; set; }
        public string Cover { get; set; }
        public string Fanart { get; set; }
    }

    public class TvEpisode
    {
        public string IdEpisode { get; set; }
        public string Title { get; set; }
        public string ShowTitle { get; set; }
        public string Plot { get; set; }
        public string Date { get; set; }
        public string MPAA { get; set; }
        public string Studio { get; set; }
        public string Season { get; set; }
        public string Episode { get; set; }
        public string FileName { get; set; }
        public string DirName { get; set; }
        public string PlayCount { get; set; }
        public string Hash { get; set; }
        public string Cover { get; set; }
        public string Fanart { get; set; }
        public string WatchedImage { get; set; }
        public Visibility Seen { get; set; }
    }

    public class MusicAlbum
    {
        public string Title { get; set; }
        public string IdAlbum { get; set; }
        public string Artist { get; set; }
        public string Genre { get; set; }
        public string IdGenre { get; set; }
        public string Year { get; set; }
        public string Cover { get; set; }
    }

    public class GenreCollection : ObservableCollection<MusicGenre>
    {
    }

    public class FilmCollection : ObservableCollection<Film>
    {
    }

    public class AlbumCollection : ObservableCollection<MusicAlbum>
    {
    }

    public class ShowCollection : ObservableCollection<TvShow>
    {
    }

    public class EpisodeCollection : ObservableCollection<TvEpisode>
    {
    }

}